// limitMaxLength with yyjob modification to avoid conflict with validation 
// open source license 
jQuery.fn.limitMaxlength = function(options){

   var settings = jQuery.extend({
      attribute: "maxcharlength",
      onLimit: function(){},
      onEdit: function(){}
   }, options);

   var setCaretPosition = function(el, pos) {
      if(el.setSelectionRange) {
         el.focus();
         el.setSelectionRange(pos,pos);
      }
      else if (el.createTextRange) {
         var range = el.createTextRange();
         range.collapse(true);
         range.moveEnd('character', pos);
         range.moveStart('character', pos);
         range.select();
      }

   };

   var getCaretPosition = function(el) {
      var start = 0, end = 0, normalizedValue, range,
          textInputRange, len, endRange;

      if (typeof el.selectionStart == "number") {
         start = el.selectionStart;
      } else {
         range = document.selection.createRange();

         if (range && range.parentElement() == el) {
            len = el.value.length;
            normalizedValue = el.value.replace(/\r\n/g, "\n");

            // Create a working TextRange that lives only in the input
            textInputRange = el.createTextRange();
            textInputRange.moveToBookmark(range.getBookmark());

            // Check if the start and end of the selection are at the very end
            // of the input, since moveStart/moveEnd doesn't return what we want
            // in those cases
            endRange = el.createTextRange();
            endRange.collapse(false);

            if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
                start = len;
            } else {
                start = -textInputRange.moveStart("character", -len);
                start += normalizedValue.slice(0, start).split("\n").length - 1;
            }
         }
      }

      return start; 
   };


   // Event handler to limit the textarea
   var onEdit = function(e){
      var textarea = jQuery(this);
      var maxlength = parseInt(textarea.attr(settings.attribute));
      if(compact_strlen(textarea.val()) > maxlength){
         var cursor = getCaretPosition(this);
         var scroll = jQuery(this).scrollTop();
         var pctlength = compact_strlen(textarea.val()); 
         if(pctlength > maxlength) {
            var allowtext = textarea.val().substr(0, maxlength);
            var numadd = 0;
            while(compact_strlen(allowtext) < maxlength) {
               allowtext = textarea.val().substr(0, maxlength+(++numadd));
            }
            textarea.val(allowtext);
         }

         setCaretPosition(this, cursor); 
         jQuery(this).scrollTop(scroll);
         
         // Call the onlimit handler within the scope of the textarea
         jQuery.proxy(settings.onLimit, this)();
      }
      // Call the onEdit handler within the scope of the textarea
      jQuery.proxy(settings.onEdit, this)((maxlength - compact_strlen(textarea.val())), maxlength);
   };

   var onKeyPress = function(e) {  
      var textarea = jQuery(this);
      var maxlength = parseInt(textarea.attr(settings.attribute));
      var keycode = e.which;
      var hasSelection = document.selection? document.selection.createRange().text.length > 0 : this.selectionStart != this.selectionEnd;  

      //return false if can't write more  
      if(compact_strlen(textarea.val()) >= maxlength && e.which !== 0 && e.charCode !== 0 && !e.ctrlKey && !e.altKey && !hasSelection) {
         return false;
      }
 
      return true;
   };     

   this.each(onEdit);

   return this.keyup(onEdit)
            .keypress(onKeyPress)
            .focus(onEdit)
            .live('input paste', onEdit);
}
